#include <mutex>
#include <condition_variable>
#include <functional>
#include <memory>
#include "buffer.hpp"
#include <thread>

namespace tqblog
{
  using Functor = std::function<void(Buffer &)>;
  class AsyncLooper
  {
  public:
    using ptr = std::shared_ptr<AsyncLooper>;
    AsyncLooper(Functor callBack)
        : _stop(false), _thread(&AsyncLooper::threadEntry, this), _callBack(callBack){};
    void stop()
    {
      _stop = true;
      _cond_con.notify_all();
    };
    ~AsyncLooper()
    {
      stop();
      _cond_con.notify_all();
      _thread.join();
    }
    void push(const char *data, size_t len)
    { // 暂存到缓冲区
      std::unique_lock<std::mutex> mtex(_mutex);
      _pro_buf.push(data, len);
      _cond_con.notify_all();
    };

  private:
    void threadEntry()
    { // 输出日志
      while (1)
      {
          {
            if(_stop&&_pro_buf.empty()) {return;}
            // std::cout<<_stop<<":"<<_pro_buf.empty()<<std::endl;
            std::unique_lock<std::mutex> mtex(_mutex);
            _cond_con.wait(mtex, [&]
                           { return !_pro_buf.empty()||_stop; });
            _con_buf.swap(_pro_buf);
          }
          _callBack(_con_buf);
          _con_buf.reset();
      }
    };

  private:
    Functor _callBack;

  private:
    bool _stop;
    Buffer _pro_buf;
    Buffer _con_buf;
    std::mutex _mutex;
    std::condition_variable _cond_pro;
    std::condition_variable _cond_con;
    std::thread _thread;
  };
};